﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace Utils.Adapter
{
    public abstract class AdapterBase : IDisposable
    {
        protected readonly HttpClient httpClient;

        public abstract string BaseUrl { get; }

        public AdapterBase()
        {
            httpClient = new HttpClient(new AdapterHttpHandler(this));
        }

        protected virtual HttpRequestMessage Filter(HttpRequestMessage httpRequest)
        {
            return httpRequest;
        }

        protected virtual HttpContent CheckParse(HttpResponseMessage httpResponse)
        {
            if (httpResponse.IsSuccessStatusCode)
            {
                return httpResponse.Content;
            }
            throw Error.ThirdError(httpResponse.StatusCode.ToString(), "接口异常");
        }


        public void Dispose()
        {
            httpClient.Dispose();
        }

        class AdapterHttpHandler : DelegatingHandler
        {
            private readonly AdapterBase adapter;

            public AdapterHttpHandler(AdapterBase adapter)
            {
                this.InnerHandler = new HttpClientHandler
                {
                    AllowAutoRedirect = true,
                    UseCookies = true,
                    AutomaticDecompression = System.Net.DecompressionMethods.GZip,
                    ClientCertificateOptions = ClientCertificateOption.Automatic
                };
                this.adapter = adapter;
            }

            private IDictionary<string, string> DefaultHeaders = new Dictionary<string, string>
                {
                    { "Accept", "text/html,application/xhtml+xml,application/xm,application/json" },
                    { "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" }
                };

            protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                request.RequestUri = new Uri(adapter.BaseUrl + request.RequestUri.PathAndQuery);
                foreach (var item in DefaultHeaders)
                {
                    request.Headers.Add(item.Key, item.Value);
                }
                var responseMessage = await base.SendAsync(adapter.Filter(request), cancellationToken);
                var obj = adapter.CheckParse(responseMessage);
                responseMessage.Content = obj;
                return responseMessage;
            }
        }
    }
}
